<?php

class x_session_store
{

	protected $session_store_path;
	protected $sid;
	protected $session_storage_deep_level;

	protected $session_path_dir;
	protected $session_path;

	protected $session_fp;
	protected $session_fp_readable = false;

	public function __construct($session_store_path, $sid, $session_storage_deep_level)
	{
		$this->session_store_path = $session_store_path;
		$this->sid = $sid;
		$this->session_storage_deep_level = $session_storage_deep_level;

		$this->set_paths();
	}

	public function __destruct()
	{
		if (is_resource($this->session_fp))
		{
			fclose($this->session_fp);
		}
	}

	public function session_exists()
	{
		return file_exists($this->session_path);
	}

	public function session_load($write_begin)
	{
		$must_load_session_from_file = false;
		if (is_resource($this->session_fp))
		{
			if ($this->session_fp_readable)
			{
				fseek($this->session_fp, 0);
				$must_load_session_from_file = true;
			}
			else
			{
				$_SESSION = array();
			}
		}
		else
		{
			if (file_exists($this->session_path))
			{
				$this->session_fp = fopen($this->session_path, "r+");
				$this->session_fp_readable = true;

				$must_load_session_from_file = true;
			}
			else
			{
				if (!file_exists($this->session_path_dir))
				{
					$this->mkdir($this->session_path_dir, true);
				}
				$this->session_fp = fopen($this->session_path, "w+");
				$this->session_fp_readable = false;

				$_SESSION = array();
			}

			if ($write_begin)
			{
				flock($this->session_fp, LOCK_EX);
			}
		}

		if ($must_load_session_from_file)
		{
			$session_data = "";
			while ($buf = fread($this->session_fp, 5120))
			{
				$session_data .= $buf;
			}
			$_SESSION = unserialize($session_data);
		}

		if (!$write_begin)
		{
			fclose($this->session_fp);
		}
	}

	protected function session_save()
	{
		if (is_resource($this->session_fp))
		{
			ftruncate($this->session_fp, 0);
			fseek($this->session_fp, 0);
			fwrite($this->session_fp, serialize($_SESSION));
			fclose($this->session_fp);
		}
	}

	public function session_delete()
	{
		if (is_resource($this->session_fp))
		{
			fclose($this->session_fp);
		}
		if (file_exists($this->session_path))
		{
			unlink($this->session_path);
			clearstatcache();
		}
	}

	public function session_write_begin()
	{
		$this->session_load(true);
		return true;
	}

	public function session_write_commit()
	{
		if (!is_resource($this->session_fp))
		{
			return false;
		}
		$this->session_save();
		return true;
	}

	public function session_write_rollback()
	{
		if (!is_resource($this->session_fp))
		{
			return false;
		}
		$this->session_load(false);
		return false;
	}

	protected function set_paths()
	{
		$this->session_path_dir = $this->session_store_path;
		for ($i = 0; $i < $this->session_storage_deep_level; $i++)
		{
			$this->session_path_dir .= "/" . substr($this->sid, $i, 1);
		}
		$this->session_path = $this->session_path_dir . "/" . $this->sid . ".session";
	}
	
	protected function mkdir($path, $recursive = true)
	{
		if (strtoupper(substr(PHP_OS, 0, 3)) == "WIN")
		{
			$path = str_replace("/", "\\", $path);
		}
		mkdir($path, 0700, $recursive);
	}

}

?>